package channelService

import (
	"errors"
	"fmt"
	"gitee.com/fierce_wolf/go-fox-edge-common/commLogger"
	"gitee.com/fierce_wolf/go-fox-edge-common/commRedisRpc"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Map"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Method"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/SyncMap"
	"go-fox-edge-channel-serial-analyzer/channelEntity"
	"go-fox-edge-channel-serial-analyzer/script"
)

type channelService struct {
}

func (e *channelService) OpenChannel(channelName string, channelParam map[string]interface{}) error {
	manufacturer := channelParam["manufacturer"]
	deviceType := channelParam["deviceType"]
	splitHandler := channelParam["splitHandler"]

	// 必选项
	if Method.HasEmpty(manufacturer, deviceType, splitHandler) {
		return errors.New("参数不能为空: manufacturer, deviceType, splitHandler")
	}

	// 构造脚本引擎的绑定关系
	serialChannelEntity := &channelEntity.SerialChannelEntity{}
	serialChannelEntity.ChannelParam = make(map[string]interface{})
	e.rebindScriptEngine(serialChannelEntity, channelParam)

	SyncMap.SetValue(channelEntity.Map, channelName, serialChannelEntity)

	return nil
}

func (e *channelService) rebindScriptEngine(channelEntity *channelEntity.SerialChannelEntity, channelParam map[string]interface{}) (err error) {
	// 定义一个最终的异常拦截，用来防止可能的代码BUG
	defer func() {
		if r := recover(); r != nil {
			message := fmt.Sprintf("rebindScriptEngine()捕获到异常:%v", r)
			commLogger.Console.Error(message)
			err = errors.New(message)
		}
	}()

	Map.Append(channelEntity.ChannelParam, channelParam)

	// 获得操作实体:splitOperate，必选项目
	splitOperate, err := script.GetSplitOperate(channelParam)
	if err != nil {
		return err
	}

	splitScript, err := script.BuildSplitOperate(splitOperate)
	if err != nil {
		return err
	}

	channelEntity.SplitScript = splitScript
	channelEntity.SplitOperate = splitOperate

	// 获得操作实体:keyHandler，可选项目
	keyHandler := channelParam["keyHandler"]
	if !Method.HasEmpty(keyHandler) {
		keyOperate, err := script.GetKeyOperate(channelParam)
		if err != nil {
			return err
		}

		keyScript, err := script.BuildServiceKeyOperate(keyOperate)
		channelEntity.KeyScript = keyScript
		channelEntity.KeyOperate = keyOperate
	}
	return nil
}

func (e *channelService) CloseChannel(channelName string, channelParam map[string]interface{}) error {
	SyncMap.DelValue(channelEntity.Map, channelName)
	return nil
}

func (e *channelService) Report() ([]*commRedisRpc.ChannelRespondVO, error) {
	return report.popAll()
}
